package com.uniriho.lxr5002_service.moudel;

import android.annotation.SuppressLint;

import android.content.Context;
import android.content.IntentFilter;

import android.location.GnssStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.net.ConnectivityManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.provider.Settings;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.lifecycle.ViewModel;

import com.google.gson.Gson;
import com.sdk.devicemanager.DEVICEcon;
import com.uniriho.lxr5002_service.Constants;
import com.uniriho.lxr5002_service.been.OtherData;
import com.uniriho.lxr5002_service.been.RequestBean;
import com.uniriho.lxr5002_service.gpsutils.GPSUtils;
import com.uniriho.lxr5002_service.gpsutils.GPS_Interface;
import com.uniriho.lxr5002_service.gpsutils.GPS_Observe;
import com.uniriho.lxr5002_service.internet.OkHttpUtil;
import com.uniriho.lxr5002_service.receiver.NetWorkStateReceiver;
import com.uniriho.lxr5002_service.receiver.NetWork_Interface;
import com.uniriho.lxr5002_service.utils.LogUtils;
import com.uniriho.lxr5002_service.utils.SpUtils;
import com.uniriho.lxr5002_service.utils.TimerUtils;

import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@SuppressLint("StaticFieldLeak")
public class GPSMoudel extends ViewModel implements GPS_Interface, NetWork_Interface, TimerUtils.TimeListener {
    private TimerUtils timerUtils;
    private String posNumber = "";
    private String flashID;
    private LocationManager mLocationManager;
    private final String TAG = "GPSMoudel";
    private Context mContext;
    private NetWorkStateReceiver netWorkStateReceiver;
    private GPS_Observe gpsObserve;
    private int timeOut = 0;
    private String newUrl = "";
    private String chipCode = "";
    private boolean GPSSwitchState = false;
    private boolean ISGPSING = false;
    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
        }
    };

    private Location mLocation;
    private boolean isUpdate = false;
    private boolean netState = false;
    private boolean isTestNewUrl = false;
    private Handler mainHandler;

    @SuppressLint("MissingPermission")
    public GPSMoudel(Context context) {
        this.mContext = context.getApplicationContext();
        //判断是否需要上传
        if (SpUtils.getInstance(mContext).getUpdateState() == 100) {
            LogUtils.debug(TAG, "无需上传");
            destroy();
            return;
        }
        //起爆器编号
        DEVICEcon devicEcon = new DEVICEcon(mContext);
        posNumber = devicEcon.get_sys_parameter(2).replace("\n","");
        //获取流水号
        flashID = devicEcon.get_sys_parameter(1).trim();
        if (flashID.isEmpty()) {
            LogUtils.error(TAG, "流水号获取失败");
//            Toast.makeText(context, "流水号或起爆器编号获取失败", Toast.LENGTH_SHORT).show();
            return;
        }

        //获取控制卡编号
        chipCode = getChipCode();
        mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
        if (mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            mLocationManager.registerGnssStatusCallback(mStatusListener);
            mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000,
                    0, mLocationListener);
            mLocation = getLastKnownLocation();
        }
        LogUtils.debug("lastLocation", mLocation + "");

        //注册网监听
        registerNetReciever();
        //开始监听GPS开关状态
        registerGpsListener();

        //1.判断GPS是否一打开，如果一打开，直接定位
        if (GPSUtils.getInstance(mContext).isOPen()) {
            openOrCloseGps(true);
            GPSSwitchState = true;
        }
        timerUtils = new TimerUtils();
        timerUtils.setTimeListener(this);
    }

    /**
     * 获取控制卡编号
     * @return
     */
    private String getChipCode() {
        //persist.sys.chipcode
        try {
            Class<?> c = Class.forName("android.os.SystemProperties");
            Method get = c.getMethod("get", String.class);
            Object invoke = get.invoke(c, "persist.sys.chipcode");
            if (invoke != null) {
                String mycode = invoke.toString();
                LogUtils.debug("getChipCode", mycode);
                if (mycode.length() != 48) {
                    return "";
                }
                chipCode = mycode.toUpperCase();
                if (chipCode.startsWith("1EFFFF") && chipCode.endsWith("2E")) {
                    chipCode = asciiToString(chipCode.substring(chipCode.length() - 30, chipCode.length() - 4));
                    LogUtils.debug("getChipCode", "chipCode:" + chipCode);
                    return chipCode;
                } else {
                    return "";
                }
            }
            return "";
        } catch (Exception e) {
            e.printStackTrace();
            LogUtils.debug("getChipCode",e.toString());
            return "";
        }
    }

    /**
     * 将16进制 ASCII转成字符串
     *
     * @param hexValue
     * @return
     */
    public static String asciiToString(String hexValue) {
        StringBuffer sbu = new StringBuffer();
        for (int i = 0; i < hexValue.length(); i += 2) {
            sbu.append((char) Integer.parseInt(hexValue.substring(i, i + 2), 16));
        }
        return sbu.toString();
    }

    private Runnable gpsTimeOutRunnable = new Runnable() {
        @Override
        public void run() {
            timeOut++;
            if (timeOut >= Constants.GPS_TIMEOUT) {
                if (mLocation == null) {
                    LogUtils.debug(TAG, "定位超时");
//                    Toast.makeText(mContext, "定位超时", Toast.LENGTH_SHORT).show();
                    timerUtils.startTimer();
                    openOrCloseGps(false);
                    timeOut = 0;
//                    destroy();
                    return;
                }
            }
            handler.postDelayed(gpsTimeOutRunnable, 1000);
        }
    };

    @SuppressLint("MissingPermission")
    public void openOrCloseGps(boolean enable) {
        LogUtils.debug("openOrCloseGps", enable+"");
        //开启定位，并且没有在定位中，执行定位
        if (enable&&!ISGPSING) {
            try {
                handler.postDelayed(gpsTimeOutRunnable, 1000);
                LogUtils.debug("openOrCloseGps", "定位启动");
//                Toast.makeText(mContext, "定位开启", Toast.LENGTH_SHORT).show();
                ISGPSING = true;
                Settings.Secure.setLocationProviderEnabled(mContext.
                        getContentResolver(), LocationManager.GPS_PROVIDER, true);
                mLocationManager.registerGnssStatusCallback(mStatusListener);
                mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000,
                        0, mLocationListener);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //关闭定位，无论是否定位中，直接关闭定位。
        if (!enable){
            try {
                mLocationManager.removeUpdates(mLocationListener);
                mLocationManager.unregisterGnssStatusCallback(mStatusListener);
                Settings.Secure.setLocationProviderEnabled(mContext.
                        getContentResolver(), LocationManager.GPS_PROVIDER, false);
                LogUtils.debug("openOrCloseGps", "closeGPS");
                ISGPSING = false;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * GPS定位监听
     */
    private LocationListener mLocationListener = new LocationListener() {

        //GPS状态变化时触发
        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            switch (status) {
                //GPS状态为可见时
                case LocationProvider.AVAILABLE:
//                    Log.e(TAG, "当前GPS状态为可见状态");
                    break;
                //GPS状态为服务区外时
                case LocationProvider.OUT_OF_SERVICE:
//                    Log.e(TAG, "当前GPS状态为服务区外状态");
                    break;
                //GPS状态为暂停服务时
                case LocationProvider.TEMPORARILY_UNAVAILABLE:
//                    Log.e(TAG, "当前GPS状态为暂停服务状态");
                    break;
            }
        }

        //GPS开启时触发
        @Override
        public void onProviderEnabled(String provider) {
            LogUtils.debug(TAG, "onProviderEnabled");
        }

        //GPS禁用时触发
        @Override
        public void onProviderDisabled(String provider) {
            LogUtils.debug(TAG, "onProviderDisabled");
        }

        //位置信息变化时触发
        @Override
        public void onLocationChanged(Location location) {
            mLocation = location;
            LogUtils.debug(TAG, "onLocationChanged");
            LogUtils.debug("onLocationChanged", "定位成功");
//            Toast.makeText(mContext, "定位成功", Toast.LENGTH_SHORT).show();
            timerUtils.stopTimer();

            //判断当前是否有网络,如果有网络，直接上传，如果无网络，交给网络监听结果上传。
            if (netState) {
                updateGPS(location);
            }
            //停止GPS定位
            openOrCloseGps(false);
        }
    };

    /**
     * GPS状态监听
     */
    private final GnssStatus.Callback mStatusListener = new GnssStatus.Callback() {
        @Override
        public void onStarted() {
            super.onStarted();
            LogUtils.debug(TAG, "GPS_EVENT_STARTED");
        }

        @Override
        public void onStopped() {
            super.onStopped();
            LogUtils.debug(TAG, "GPS_EVENT_STOPPED");
            mLocationManager.removeUpdates(mLocationListener);
        }

        @Override
        public void onFirstFix(int ttffMillis) {
            super.onFirstFix(ttffMillis);
            LogUtils.debug(TAG, "第一次定位");
        }

        @Override
        public void onSatelliteStatusChanged(@NonNull GnssStatus status) {
            super.onSatelliteStatusChanged(status);
            //获取卫星颗数的默认最大值
            int maxSatellites = status.getSatelliteCount();
            LogUtils.debug("onGpsStatusChanged", "卫星总个数:" + maxSatellites);
            for (int i = 0; i < maxSatellites; i++) {
                LogUtils.debug("onGpsStatusChanged", "卫星标识号：" + status.getSvid(i));
                LogUtils.debug("onGpsStatusChanged", "卫星信号强度：" + status.getCn0DbHz(i));
            }
        }
    };

    /**
     * 更新位置信息
     *
     * @param location
     */
    private void updateGPS(Location location) {
        if (location != null) {
            //经度
            double Longitude = location.getLongitude();
            //纬度
            double Latitude = location.getLatitude();
            LogUtils.debug("updateGPS", "经度：" + Longitude
                    + "\r\n纬度：" + Latitude);
            // TODO: 2024/8/27  获取爆破次数和sam卡编号
            RequestBean requestBean = new RequestBean
                    (flashID, posNumber, Longitude, Latitude, new OtherData(Build.DISPLAY,chipCode,"123456789","200"));
            String sendJson = new Gson().toJson(requestBean);
            LogUtils.debug("sendJson", sendJson);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    String url;
                    if (isTestNewUrl) {
                        url = newUrl;
                    } else {
                        url = SpUtils.getInstance(mContext).getURL();
                    }
                    String response = OkHttpUtil.getInstance().postBean(url, requestBean);
                    if (response != null) {
                        LogUtils.error(TAG, response);
                        analysisResponse(response);
                    }
                }
            }).start();
        }
    }

    /**
     * 处理上传后返回结果
     *
     * @param response
     */
    private void analysisResponse(String response) {
        try {
            int index1 = response.indexOf("{");
            int index2 = response.indexOf("}") + 1;
            String mresponse = response.substring(index1, index2);
            LogUtils.debug("response", mresponse);
            Map<String, Object> map = getMap(mresponse);
            int result = (int) map.get("result");
            String url = ((String) Objects.requireNonNull(map.get("url"))).trim();
            LogUtils.debug(TAG, "result==" + result);
            LogUtils.debug(TAG, "url==" + url);
            if (isTestNewUrl) {
                if (result == 0 || result == 100) {
                    //保存新的URL
                    LogUtils.debug(TAG, "new url update fail");
                    SpUtils.getInstance(mContext).saveURL(newUrl);
                } else {
                    LogUtils.debug(TAG, "new url update success");
                }
                isUpdate = true;
                destroy();
                return;
            }

            if (result == 0) {
                LogUtils.debug(TAG, "updata success");
                if (mainHandler == null) {
                    mainHandler = new Handler(Looper.getMainLooper());
                }

            } else if (result == 100) {
                //更新下次上传状态
                SpUtils.getInstance(mContext).saveUpdateState(result);
                LogUtils.debug(TAG, "update success,result == 100");
            } else {
                LogUtils.debug(TAG, "update fail");
                if (mainHandler == null) {
                    mainHandler = new Handler(Looper.getMainLooper());
                }
            }

            if (!url.equals("")) {
                newUrl = url;
                LogUtils.debug(TAG, "new URL：" + url);
                //用新的URL上传测试
                isTestNewUrl = true;
                updateGPS(mLocation);
            }
            isUpdate = true;
            destroy();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 注册网络监听
     */
    private void registerNetReciever() {
        if (netWorkStateReceiver == null) {
            netWorkStateReceiver = new NetWorkStateReceiver(this);
        }
        IntentFilter filter = new IntentFilter();
        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        mContext.registerReceiver(netWorkStateReceiver, filter);
        LogUtils.debug(TAG, "registerNetReceiver");
    }

    /**
     * 取消注册网络监听
     */
    private void unregisterNetReciever() {
        if (netWorkStateReceiver != null) {
            mContext.unregisterReceiver(netWorkStateReceiver);
            netWorkStateReceiver = null;
            LogUtils.debug(TAG, "unregisterNetReciever");
        }
    }

    /**
     * 注册GPS开关状态监听
     */
    private void registerGpsListener() {
        gpsObserve = new GPS_Observe(mContext, this);
    }

    /**
     * 取消注册GPS开关状态监听
     */
    private void unregisterGpsListener() {
        if (gpsObserve != null) {
            gpsObserve.onDestroy();
            gpsObserve = null;
        }
    }

    /**
     * GPS 开关状态回调
     *
     * @param gpsOpen
     */
    @Override
    public void gpsSwitchState(boolean gpsOpen) {
        //定位关闭，取消计时
        //定位打开，开始定位，取消计时
        timerUtils.stopTimer();
        LogUtils.debug(TAG, "gpsSwitchState：" + gpsOpen);
        openOrCloseGps(gpsOpen);
        GPSSwitchState = gpsOpen;

    }

    /**
     * 释放资源
     */
    public void destroy() {
        unregisterGpsListener();
        unregisterNetReciever();
        openOrCloseGps(false);
    }

    /**
     * 网络监听回调
     *
     * @param state
     */
    @Override
    public void netWorkState(boolean state) {

        //获取网络连接状态
        LogUtils.debug(TAG, "netWorkState：" + state);
        if (state) {
            netState = true;
        } else {
            netState = false;
            return;
        }
        //判断如果定位成功，上传GPS信息 并取消网络监听
        if (mLocation != null && !isUpdate) {
            updateGPS(mLocation);
        }
    }

    /**
     * 将json 数组转换为Map 对象
     *
     * @param jsonString
     * @return
     */
    public Map<String, Object> getMap(String jsonString) {
        JSONObject jsonObject;
        try {
            jsonObject = new JSONObject(jsonString);
            @SuppressWarnings("unchecked")
            Iterator<String> keyIter = jsonObject.keys();
            String key;
            Object value;
            Map<String, Object> valueMap = new HashMap<String, Object>();
            while (keyIter.hasNext()) {
                key = (String) keyIter.next();
                value = jsonObject.get(key);
                valueMap.put(key, value);
            }
            return valueMap;
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取GPS location
     *
     * @return
     */
    @SuppressLint("MissingPermission")
    private Location getLastKnownLocation() {
        List<String> providers = mLocationManager.getProviders(true);
        Location bestLocation = null;
        for (String provider : providers) {
            Location l = mLocationManager.getLastKnownLocation(provider);
            if (l == null) {
                continue;
            }
            if (bestLocation == null || l.getAccuracy() < bestLocation.getAccuracy()) {
                // Found best last known location: %s", l);
                bestLocation = l;
            }
        }
        return bestLocation;
    }

    @Override
    public void startGPS() {
        //GPS 开关如果打开，重新定位
        if (GPSSwitchState) {
            if (mainHandler == null) {
                mainHandler = new Handler(Looper.getMainLooper());
            }
            mainHandler.post(new Runnable() {
                @Override
                public void run() {
                    openOrCloseGps(true);
                }
            });
        }

    }
}